/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cz.vse.adventura.po1715.xshet00_shevtsova.gui;


import cz.pecinovsky.english.pojj.adv_framework.game_gui.IGameG;
import cz.pecinovsky.english.pojj.adv_framework.game_gui.IUIG;
import cz.pecinovsky.english.pojj.adv_framework.game_txt.IGame;
import cz.pecinovsky.english.pojj.adv_framework.test_util._Test_115;
import cz.vse.adventura.po1715.xshet00_shevtsova.Obecne;
import cz.vse.adventura.po1715.xshet00_shevtsova.hra.Hra_destnik;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 ** Instance třídy {@code GUI_2}přestavují grafické
 * uživatelské rozhraní hry implementující rozhraní {@link IGameG}.
 * <br><br>
 * Oproti minulé verzi:
 * <ul>
 *   <li>Vypisuje odpovědi hry do editačního pole,</li>
 *   <li>Vizuálně odlišuje zadné příkazy a odpovědí programu,</li>
 *   <li>Ukazuje možné využití HTML značek pro odlišení příkazů a odpovědí.</li>
 *   <li>Přesouvá vstupní pole pod výstup (tj. do jižní zóny),
 *     protože při skrolujícím výstupu je takovéto uspořádní přirozenější.</li>
 *   <li>Pro zkrácení těla konstruktoru přesouvá definici posluchače
 *     vstupního pole z anonymní třídy definované v konstruktoru
 *     do interní třídy definované samostatně, avšak v rámci třídy.</li>
 *   <li>Změnila se testovací metoda, takže nyní je možno zadávat
 *     předem připravené příkazy z nějakého scénáře.</li>
 * </ul>
 *
 * @author TShevtsova
 */
public class GUI_2_Shevtsova implements IUIG {
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================


    /** Pozice aplikačního okna připravená práci na počítači s více monitory. */
    private static final Point POZICE_0 = Obecne.POZICE_0;

    /** Implicitní hra použitá v případě, že nebude zadána žádná jiná. */
    private static final IGameG IMPLICITNÍ_HRA = Hra_destnik.getHra();


//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================

    /** Aplikační okno hry. */
    private final JFrame aplikačníOkno = new JFrame();

    /** Vstupní textové pole pro zadávání příkazů. */
    private final JTextField vstupníPole = new JTextField(40);

      /** Čeká na zadání příkazu, který pak předá obsluhované hře a
     *  zadaný příkaz spolu s obdrženou odpovědí zapíše do výstupního pole. */
    private final PosluchačVstupu posluchačVstupu = new PosluchačVstupu();

    /** Textová oblast, v níž se vypisují odpovědi hry na zadané příkazy.
     *  Zakomentovaná deklarace sumožňuje porovnání schopnosti použité
     *  komponenty typu {@link JEditorPane} oproti často používané
     *  komponentě typu {@link JTextArea}. */
//    private final JTextArea výstupníPanel;
    private final JEditorPane výstupníPanel = new JEditorPane("text/html", "");

    /** Objekt určený pro postupné skládání jednotlivých odpovědí hry
     *  do jednoho souvislého textového řetězce. */
    private final StringBuilder skládačVýstupu = new StringBuilder();



    /** Návěští vypisující odpovědi hry. */
    private final JLabel lblOdpověď = new JLabel();
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================

    /** Hra, kterou dané gui právě ovládá. */
    private IGameG ovládanáHra;

//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================
 public GUI_2_Shevtsova()
      {
        //Panel pro zadávání příkazů (JIH)
        vstupníPole.addActionListener(posluchačVstupu);
        JPanel dolniPanel    = new JPanel();
        JLabel popisekVstupu = new JLabel("Zadej prikaz:");
        dolniPanel.add(popisekVstupu);
        dolniPanel.add(vstupníPole);
        aplikačníOkno.add(dolniPanel, BorderLayout.SOUTH);

        //Panel, kam se budou vypisovat zprávy hry (STŘED)
        výstupníPanel.setEditable(false);
        JScrollPane posuvnik = new JScrollPane(výstupníPanel);
        posuvnik.setPreferredSize(new Dimension (400,300));
        aplikačníOkno.add( posuvnik, BorderLayout.CENTER );

        //Zviditelnění aplikačního okna a úprava jeho velikosti a umístění
        aplikačníOkno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        aplikačníOkno.pack();
        aplikačníOkno.setVisible(true);
        aplikačníOkno.setLocation(POZICE_0);
    }

//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
 /***************************************************************************
     * Vrátí jméno autora/autorky programu ve tvaru "PŘÍJMENÍ Křestní",
     * tj. příjmení jako první a velkými písmeny, pak křestní jméno.
     *
     * @return Jméno autora/autorky programu ve tvaru PŘÍJMENÍ Křestní
     */
//    @Override
    public String getAuthor()
    {
        return Obecne.AUTOR;
    }


    /***************************************************************************
     * Vrátí xname autora/autorky programu zapsané valkými písmeny.
     *
     * @return XNAME autora/autorky programu zapsané valkými písmeny
     */
//    @Override
    public String getXNAME()
    {
        return Obecne.XNAME;
    }

 /***************************************************************************
     * Spustí komunikaci touto instancí a zadanou hrou, která musí být
     * ve skutečnosti instancí rozhraní {@link IGameG}
     * a která nevíc nesmí být ještě rozběhnutá - rozbíhá ji až GUI.
     *
     * @param hra Hra, kterou ma dané GUI spustit
     * @throws IllegalArgumentException Pokud zadaná hra neimplementuje
     *         rozhraní {@link IGameG} nebo pokud je již rozběhnutá
     */
   @Override
    public void startGame(IGame hra)
    {
        if (! (hra instanceof IGameG)) {
            throw new IllegalArgumentException( "\nSpouštěná hra" +
                "neimplementuje rozhraní adventura_115_10J.rámec.IGameG");
        }
        if (! hra.isReady()) {
            throw new IllegalArgumentException(
                "\nPřed dalším spuštěním je třeba hru nejprve ukončit");
        }
        this.ovládanáHra = (IGameG)hra;          //Zapamatuje si ovládanou hru
        aplikačníOkno.setTitle(hra.getAuthor()); //Podepíše aplikační okno

        výstupníPanel.setText("");
        skládačVýstupu.setLength(0);
        skládačVýstupu.append("<html>");

        //Hru odstartujeme zadáním prázdného příkazu
        executeCommand("");

        //Od této chvíle přebírá řízení hry posluchač vstupního pole
    }

    /***************************************************************************
     * Spustí komunikaci mezi implicitní hrou (ta nesmí v danou chvíli běžet)
     * a danou instancí GUI mající na starosti komunikaci s uživatelem.
     */
//    @Override
    public void startGame()
    {
        ovládanáHra = IMPLICITNÍ_HRA;
        startGame(ovládanáHra);
    }



//+++ Přidáno pro rozšířené zadání v předmětu 4IT115 +++++++++++++++++++++++++++

    /***************************************************************************
     * Zpracuje příkaz předaný v parametru jako by byl zadán standardním
     * postupem z klávesnice. Metoda umožňuje testovat reakce daného
     * uživatelského rozhraní na příkazy zadávané z klávesnice.
     *
     * @param příkaz Zadávaný příkaz
     */
    @Override
    public void executeCommand(String příkaz)
    {
        vstupníPole.setText(příkaz);

        //Nemusím zadávat parametr volané metody,
        //protože ta si potřebné informce zjistí od pole txfVstup
        posluchačVstupu.actionPerformed(null);
    }



//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================
//== INTERNÍ DATOVÉ TYPY =======================================================
 /***************************************************************************
     * Instance třídy "poslouchá" události ve vstupním poli,
     * do nějž se zadávají příkazy, předá zadaný příkaz obsluhované hře
     * a zadaný příkaz spolu s obdrženou odpovědí zapíše do výstupního pole.
     */
    private class PosluchačVstupu implements ActionListener
    {
        /***********************************************************************
         * Požadovaným způsobem zareaguje na zadání příkazu,
         * tj. předá příkaz hře, převede její odpověď do formát HTML
         * a přidá ji spolu se zadaným příkazem na konec výpisu akcí.
         * Zabezpečí přitom, že zadaný příkaz je vysazen tučně a
         * odpověď hry netučně.
         *
         * @param e Nastalá událost
         */
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String příkaz = vstupníPole.getText();
            skládačVýstupu.append("<b>").append(příkaz).append("</b><br>");

            String odpověď = ovládanáHra.executeCommand(příkaz);
            odpověď = odpověď.replace("\n", "<br>");
            skládačVýstupu.append(odpověď).append("<br><br>");
            výstupníPanel.setText(skládačVýstupu + "</html>");

            //Následující zakomentovaný příkaz umožňuje vyzkoušet
            //chování výstupu v případě, že odpověď hry nebude převedena
            //do formátu HTML. K tomu je potřeba zakomentovat předchozí
            //dva příkazy a odkomentovat následující příkaz
            //                výstupníPanel.append(odpoved);
            vstupníPole.setText(""); //Vyprázdnění obsahu vstupního pole
            //Přesunutí kurzoru na konec série zpráv, čímž dosáhneme
            //přesunutí posuvníku a zobrazení tohoto konce
            výstupníPanel.setCaretPosition(výstupníPanel.getDocument().
                                           getLength());
            aplikačníOkno.pack();
            vstupníPole.requestFocus();
        }
    }



    //== TESTY A METODA MAIN =======================================================

    /***************************************************************************
     * Testovací metoda.
     */
    public static void test()
    {
        GUI_2_Shevtsova gui = new GUI_2_Shevtsova();
     IGameG hra    = IMPLICITNÍ_HRA;
        _Test_115 test = _Test_115.getInstance(hra, gui);
        test.playGameByTestScenario();

        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main( String[] args )  {  test();  }
}
